#include"ThreadPool.h"

int n=1;

ThreadPool::ThreadPool(int min,int max):m_minthread(min),m_maxthread(max),m_curthread(min),m_idlethread(min),
m_stop(false),m_exitthread(0)
{
    m_manager= new std::thread(&ThreadPool::manager,this);

    for(int i=0;i<min;i++)
    {
        std::thread t(&ThreadPool::worker,this);
        std::cout<<"创建工作线程:"<<t.get_id()<<std::endl;
        m_workers.insert(make_pair(t.get_id(),std::move(t)));
    }
}

ThreadPool::~ThreadPool() {
    m_stop.store(true);
    m_cond.notify_all();  // 唤醒所有等待的线程
    
    // 等待管理线程结束
    if (m_manager->joinable()) {
        std::cout<<"管理者线程 "<<(*m_manager).get_id()<<"退出成功"<<std::endl;
        m_manager->join();
    }
    delete m_manager;
    
    // 等待所有工作线程结束
    for (auto& pair : m_workers) {
        if (pair.second.joinable()) {
            pair.second.join();
            std::cout<<"工作线程 "<<pair.first<<"退出成功"<<std::endl;
        }
    }
}

void ThreadPool::addTaks(std::function<void()> task)
{
    {
    std::lock_guard<std::mutex> lock(m_queuemutex);
    m_taskqueue.push(task);
    }
    m_cond.notify_one();
}
void ThreadPool::manager(void){
        while(!m_stop.load())
        {
            std::this_thread::sleep_for(std::chrono::microseconds(10));
            std::cout<<"i am manager i am alive curthread :  "<<m_curthread<<" m_taskqueue.size :"<<m_taskqueue.size()<<"\n";
            if(m_taskqueue.size()>m_curthread&&m_curthread<m_maxthread)
            {
                std::cout<<"i am manager i am alive\n";
                std::thread t(&ThreadPool::worker,this);
                std::cout<<"添加工作线程:"<<t.get_id()<<std::endl;
                m_workers.insert(make_pair(t.get_id(),std::move(t)));
                m_curthread++;
                m_idlethread++;
            }
            else if(m_idlethread>m_curthread/2&&m_curthread>m_minthread)
            {
               //每次销毁两个线程
                for(int i=0;i<2;i++)
                {
                    if(m_curthread>m_minthread)
                    {
                        m_exitthread++;
                        m_cond.notify_one();
                    }
                }
                std::unique_lock<std::mutex> idlock(m_idsmutex);
                for(auto it : m_exitthreadid){
                    auto findit=m_workers.find(it);
                    if(findit!=m_workers.end())
                    {
                        findit->second.join();//这里为什么要用join?
                        //因为join会阻塞当前线程，直到子线程结束
                        //如果不join，子线程会在后台继续运行
                        //但是我们已经设置了m_stop=true，所以子线程会退
                        m_workers.erase(findit);
                        std::cout<<"========== 线程"<<findit->first<<"退出成功 =========="<<std::endl;
                    }
                }
            }
        }
}

void ThreadPool::worker(void){
   while(!m_stop.load())
   {
        std::cout<<"i am worker: "<<std::this_thread::get_id()<<" i am alive \n";
        std::function<void()> task=nullptr;
       {
        std::unique_lock<std::mutex> lock(m_queuemutex);
        while(!m_stop.load()&&m_taskqueue.empty())
        {
            m_cond.wait(lock);//等待互斥锁，后抢夺互斥锁加锁
            if(m_exitthread>0)
            {
                m_curthread--;
                m_idlethread--;
                m_exitthread--;
                std::unique_lock<std::mutex> idlock(m_idsmutex);
                std::cout<<"线程退出 "<<std::this_thread::get_id()<<std::endl;
                m_exitthreadid.push_back(std::this_thread::get_id());
                return ;
            }
        }
        if(!m_taskqueue.empty())
        {
            std::cout<<"取出来一个任务"<<n++<<std::endl;
            std::cout<<"目前任务队列长度: "<<m_taskqueue.size()<<"\n";
            task=std::move(m_taskqueue.front()); //防止拷贝，提升效率
            m_taskqueue.pop();
        }
       }
        if(task)
        {
            m_idlethread--;
            task();
            m_idlethread++;
        }
   }
}

void calc(int x,int y)
{
    int z=x+y;
    std::cout<<"z= "<<z<<std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

int calc1(int x,int y)  //尝试用future模板类存储任务函数返回值 /异步类   
//promise类 传递到线程内部，但他返回的也是future
//package_task 打包任务函数，传递到线程内部，可以打包任务函数，最终返回future对象 
{
    int z=x+y;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return z;
}

// int main()
// {
//     std::cout<<"hello world"<<std::endl;
//     ThreadPool pool;
//     std::vector<std::future<int>> res;
//     for(int i=0;i<40;i++)
//     {
//         //可调用对象绑定
//         // auto obj=std::bind(calc,i,i*2);
//         // pool.addTaks(obj);
//         res.emplace_back(pool.addTaks(calc1,i,i*2));
//     }

//     for(auto & p: res)
//     {
//         std::cout<<"线程执行的结果 :"<<p.get()<<std::endl;
//     }
//     return 0;
// }